package com.mgs.product.tagger.dao
{
	import com.mgs.product.tagger.controller.ContextController;
	import com.mgs.product.tagger.model.Axis;
	import com.mgs.product.tagger.model.Classifiable;
	import com.mgs.product.tagger.model.Classification;
	import com.mgs.product.tagger.model.Document;
	import com.mgs.product.tagger.model.Segment;
	
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.utils.Dictionary;
	
	import mx.utils.StringUtil;
	
	public class ClassificationDaoImpl implements ClassificationDao
	{
		private var root:XML;
		
		private var segmentId:int;
		private var map:Dictionary;
		
		public function ClassificationDaoImpl()
		{
			//TODO: implement function
		}
		
		public function save(repository:File, classification:Classification):void
		{
			segmentId = 1;
			root = <classif/>;
			map = new Dictionary();
			classificationXml(classification);
			var stream:FileStream = new FileStream();
			stream.open(repository.resolvePath(".metadata"), FileMode.WRITE);
			
			stream.writeUTFBytes(root.toXMLString());
			
			stream.close();
			
		}
		
		private function classificationXml(classification:Classification):void
		{
			var xmlWkps:XML = <workspaces/>;
			for each(var path:String in classification.workspaces)
			{
				var xmlWkp:XML = <workspace/>;
				xmlWkp.@path = path;
				xmlWkps.appendChild(xmlWkp);
			}
			root.appendChild(xmlWkps);
			for each(var element:Classifiable in classification.elements)
			{
				elementXml(element);
			}
		}
		private function segmentXml(parent:XML, segment:Segment):XML
		{
			var xml:XML = <segment/>;
			xml.@name = segment.name;
			xml.@id = getSegmentId(segment);
			for each(var element:Classifiable in segment.taggedElements)
			{
				elementXml(element);
			}
			parent.appendChild(xml);
			return xml;
		}
		private function elementXml(element:Classifiable):void
		{
			if(!map[element])
			{
				map[element] = true;
				var xml:XML;
				if(element is Axis)
				{
					xml = <axis/>;
					for each(var segment1:Segment in (element as Axis).segments)
					{
						segmentXml(xml, segment1);
					}
				}
				else if ((element as Document).isPersistent || (element as Document).tags.length > 0 || !((element as Document).offset == null || (element as Document).offset.length == 0))
				{
					xml = <document/>;
					xml.@uc = (element as Document).uniqueCode;
					xml.@offset = (element as Document).offset;
				}
				if(xml != null)
				{
					xml.@name = element.name;
					for each(var segment:Segment in element.tags)
					{
						xml.appendChild(<tag>{getSegmentId(segment)}</tag>);
						// segmentXml(segment);
					}
					root.appendChild(xml);
				}
			}
		}
		
		private function getSegmentId(segment:Segment):String
		{
			if(!map[segment])
			{
				map[segment] = "" + segmentId;
				segmentId += 1;
			}
			return map[segment] as String;
		}
		
		public function load(repository:File):Classification
		{
			var classification:Classification = new Classification();
			classification.elements = new Vector.<Classifiable>();
			
			var stream:FileStream = new FileStream();
			var file:File = repository.resolvePath(".metadata");
			if(file.exists)
			{
				stream.open(file, FileMode.READ);
				
				var str:String = stream.readUTFBytes(file.size);
				
				stream.close();
				
				var xml:XML = new XML(str);
				
				map = new Dictionary();
				var map2:Object = {};
				var ct:int = 0;
				var e:XML;
				for each(e in xml.axis)
				{
					var axis:Axis = new Axis();
					axis.name = e.@name;
					axis.segments = new Vector.<Segment>();
					axis.tags = new Vector.<Segment>();
					for each(var e2:XML in e.segment)
					{
						var s:Segment = new Segment();
						s.name = e2.@name;
						s.axis = axis;
						s.taggedElements = new Vector.<Classifiable>();
						map2[e2.@id] = s;
						axis.segments.push(s);
					}
					map[ct++] = axis;
				}
				ct = 0;
				for each(e in xml.workspaces.workspace)
				{
					classification.workspaces.push(e.@path);
				}
				for each(e in xml.children())
				{
					var element:Classifiable = null;
					if(e.name() == "axis")
					{
						// Cache
						element = map[ct++] as Axis;
					}
					else if(e.name() == "document")
					{
						var doc:Document = new Document();
						doc.isPersistent = true;
						doc.name = e.@name;
						doc.offset = e.@offset;
						doc.uniqueCode = e.@uc;
						doc.file = repository.resolvePath(doc.uniqueCode);
						element = doc;
//						if(doc.file.exists)
//						{
//							element = doc;
//						}
					}
					if(element != null)
					{
						element.tags = new Vector.<Segment>();
						if(e.tag.length() == 0){
							classification.elements.push(element);
						}else{
							for each(var e3:XML in e.tag)
							{
								var t:String = e3.text();
								// Ref cache
								var s2:Segment = map2[StringUtil.trim(t)] as Segment;
								s2.taggedElements.push(element);
								element.tags.push(s2);
							}
						}
					}
				}
			}
			return classification;
		}
	}
}